package 分库分表;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 翟晓龙
 * @date 2022/3/31
 */
public class HashDivide {

    public static void main(String[] args) throws Exception {
        int dbNum = 4;
        int tableNum = 4;
        List<ShardCfg> preList = sharding(dbNum,tableNum);
        Map<Integer, List<ShardCfg>> listMap = preList.stream().collect(Collectors.groupingBy(ShardCfg::getDbIdx));
        Map<Integer,ShardCfg> preListMap = preList.stream().collect(Collectors.toMap(ShardCfg::getHash,shard -> shard));
        dbNum = dbNum * 2;
        tableNum = tableNum * 2;
        List<ShardCfg> nextList = sharding(dbNum,tableNum);
        for (ShardCfg shardCfg : nextList){
            ShardCfg preShard = preListMap.get(shardCfg.getHash());
            if (!preShard.equals(shardCfg)){
                throw new Exception("扩容失败");
            }

        }


    }

    /**
     * 非互质关系导致的数据偏斜问题
     */
    public static List<ShardCfg> sharding(int dbNum,int tableNum){

        List<ShardCfg> list = new ArrayList<>(1000);
        for (int hash = 0;hash <=10000;hash ++){
            ShardCfg shardCfg = calShard(hash,dbNum,tableNum);
            shardCfg.setHash(hash);
            list.add(shardCfg);
//            System.out.printf("hash: " + hash);
//            System.out.println(shardCfg.toString());
        }
        return list;

    }

    /**
     * 库、表分别进行计算分片序号
     * @param hash
     * @param dbNum
     * @param tableNum
     * @return
     */
    public static ShardCfg calShard(int hash,int dbNum,int tableNum){

        return new ShardCfg(Math.abs(hash % dbNum),Math.abs(hash % tableNum));
        
    }

    /**
     * 用总表数计算分片序号
     * @param hash
     * @param dbNum
     * @param tableNum
     * @return
     */
    public static ShardCfg calShard2(int hash,int dbNum,int tableNum){
        // 总分片数
        int totalSlot = dbNum * tableNum;
        // 分片序号
        int slot = Math.abs(hash % totalSlot);
        //
        return new ShardCfg(Math.abs(slot % dbNum),Math.abs(slot / dbNum));
    }
}
